<template>
  <el-dialog
    v-model="dialogState.visible"
    :append-to-body="dialogState.appendToBody"
    :center="dialogState.center"
    class="form-dialog-qvil"
    :close-on-click-modal="dialogState.closeOnClickModal"
    :close-on-press-escape="dialogState.closeOnPressEscape"
    :destroy-on-close="dialogState.destroyOnClose"
    :draggable="dialogState.draggable"
    :fullscreen="dialogState.fullscreen"
    :lock-scroll="dialogState.lockScroll"
    :modal="dialogState.modal"
    :show-close="dialogState.showClose"
    :title="dialogState.title"
    :top="dialogState.top"
    :width="dialogState.width"
    @close="handleClose"
  >
    <el-form ref="formRef" v-loading="formState.loading" label-position="top" :model="formState.data" :rules="formRules">
      <el-row :gutter="20">
        <template v-for="field in visibleFields" :key="field.prop">
          <el-col :span="getFieldSpan(field)">
            <el-form-item :label="field.label" :prop="field.prop" :required="field.required" :rules="field.rules">
              <component
                :is="getComponent(field.component)"
                v-model="formState.data[field.prop]"
                v-bind="getComponentProps(field)"
                :disabled="field.disabled"
              >
                <template v-if="field.component === 'select' && (field.options || field.componentProps?.options)">
                  <el-option
                    v-for="option in field.options || field.componentProps?.options"
                    :key="option.value"
                    :disabled="option.disabled"
                    :label="option.label"
                    :value="option.value"
                  />
                </template>
              </component>
            </el-form-item>
          </el-col>
        </template>
      </el-row>

      <!-- 自定义表单内容 -->
      <slot :form="formState.data" name="form-content" />
    </el-form>

    <template #footer>
      <div class="dialog-footer">
        <el-button @click="handleCancel">取消</el-button>
        <el-button :loading="formState.submitting" type="primary" @click="handleConfirm">确定</el-button>
      </div>
    </template>
  </el-dialog>
</template>

<script lang="ts" setup>
import { ElCascader, ElDatePicker, ElInput, ElInputNumber, ElSelect, ElSwitch, ElTimePicker } from 'element-plus'
import { computed } from 'vue'
import { useFormDialog } from './hooks/useFormDialog'
import type { FormField } from './types'

const props = defineProps<{
  modelValue: boolean
  title?: string
  width?: string | number
  fields: FormField[]
  formData?: Record<string, any>
}>()

const emit = defineEmits<{
  (e: 'update:modelValue', value: boolean): void
  (e: 'form-change', form: Record<string, any>): void
  (e: 'validation-error', fields: Record<string, any>): void
  (e: 'confirm', form: Record<string, any>): void
  (e: 'cancel'): void
}>()

const { formState, dialogState, formRef, setFormData, setLoading, setSubmitting, validate, resetFields, open, close } = useFormDialog({
  title: props.title,
  width: props.width,
  fields: props.fields,
  formData: props.formData,
})

// 可见字段
const visibleFields = computed(() => {
  return props.fields.filter((field) => field.visible !== false)
})

// 表单规则
const formRules = computed(() => {
  const rules: Record<string, any> = {}
  props.fields.forEach((field) => {
    if (field.rules) {
      rules[field.prop] = field.rules
    }
  })
  return rules
})

// 获取组件
const getComponent = (type: string) => {
  const componentMap: Record<string, any> = {
    input: ElInput,
    'input-number': ElInputNumber,
    select: ElSelect,
    switch: ElSwitch,
    'date-picker': ElDatePicker,
    date: ElDatePicker, // 增加date类型，映射到日期选择器
    'time-picker': ElTimePicker,
    cascader: ElCascader,
  }
  return componentMap[type] || ElInput
}

// 获取组件属性
const getComponentProps = (field: FormField) => {
  const props: Record<string, any> = {
    ...field.componentProps,
    style: field.fullWidth ? 'width: 100%' : undefined,
    placeholder: field.placeholder || `请输入${field.label}`,
  }

  // 处理textarea类型
  if (field.type === 'textarea') {
    props.type = 'textarea'
  }

  // 处理select组件特有属性
  if (field.component === 'select') {
    // 确保options正确传递
    if (field.options && !props.options) {
      props.options = field.options
    }

    // 多选特性
    if (field.multiple) {
      props.multiple = true
    }

    // 过滤特性
    if (field.filterable) {
      props.filterable = true
    }

    // 允许创建条目
    if (field.allowCreate) {
      props.allowCreate = true
    }

    // 默认选中第一个
    if (field.defaultFirstOption !== undefined) {
      props.defaultFirstOption = field.defaultFirstOption
    }

    // 远程搜索
    if (field.remote) {
      props.remote = true

      if (field.remoteMethod) {
        props.remoteMethod = field.remoteMethod
      }

      if (field.loading !== undefined) {
        props.loading = field.loading
      }
    }

    // 可清除选项
    if (field.clearable) {
      props.clearable = true
    }

    // 处理折叠标签属性
    if (field.componentProps?.collapseTags !== undefined) {
      props.collapseTags = field.componentProps.collapseTags
    }

    // 处理折叠标签提示属性
    if (field.componentProps?.collapseTagsTooltip !== undefined) {
      props.collapseTagsTooltip = field.componentProps.collapseTagsTooltip
    }

    // 处理下拉框样式类
    if (field.componentProps?.popperClass) {
      props.popperClass = field.componentProps.popperClass
    }

    // 处理modelValue
    if (field.componentProps?.modelValue) {
      // 确保在打开表单前处理modelValue
      const currentValue = formState.data[field.prop]
      if (currentValue !== undefined) {
        props.modelValue = field.componentProps.modelValue(currentValue)
      }
    }
  }

  return props
}

// 获取字段宽度
const getFieldSpan = (field: FormField) => {
  // 首先检查是否明确指定了colSpan
  if (field.colSpan !== undefined) return field.colSpan

  // 其次检查是否设置了fullWidth
  if (field.fullWidth === true) return 24

  // 最后使用默认值（默认为半行）
  return 12
}

// 处理关闭
const handleClose = () => {
  emit('cancel')
}

// 处理取消
const handleCancel = () => {
  emit('cancel')
}

// 处理确认
const handleConfirm = async () => {
  const valid = await validate()
  if (valid) {
    emit('confirm', formState.data)
  } else {
    emit('validation-error', formState.errors)
  }
}

// 监听 modelValue 变化
watch(
  () => props.modelValue,
  (val) => {
    // 避免无限循环
    if (val !== dialogState.visible) {
      if (val) {
        open(props.formData)
      } else {
        close()
      }
    }
  },
  { immediate: true }
)

// 监听表单数据变化
watch(
  () => formState.data,
  (val) => {
    emit('form-change', val)
  },
  { deep: true }
)

// 监听对话框状态变化
watch(
  () => dialogState.visible,
  (val) => {
    if (val !== props.modelValue) {
      emit('update:modelValue', val)
    }
  }
)

// 暴露方法
defineExpose({
  setFormData,
  setLoading,
  setSubmitting,
  validate,
  resetFields,
  open,
  close,
})
</script>

<style scoped>
.form-dialog-qvil :deep(.el-dialog) {
  border-radius: 12px;
  overflow: hidden;
  box-shadow: 0 5px 20px rgba(0, 0, 0, 0.08);
}

.form-dialog-qvil :deep(.el-dialog__header) {
  margin: 0;
  padding: 20px 24px 12px;
  border-bottom: 1px solid var(--el-border-color-lighter);
  background-color: var(--el-fill-color-blank);
}

.form-dialog-qvil :deep(.el-dialog__title) {
  font-weight: 600;
  font-size: 18px;
  color: var(--el-text-color-primary);
}

.form-dialog-qvil :deep(.el-dialog__body) {
  padding: 24px 24px 12px;
  max-height: calc(90vh - 150px);
  overflow-y: auto;
}

.form-dialog-qvil :deep(.el-dialog__footer) {
  padding: 12px 24px 24px;
  border-top: none;
  background-color: var(--el-fill-color-blank);
}

.form-dialog-qvil :deep(.el-form-item__label) {
  padding-bottom: 6px;
  font-weight: 500;
  color: var(--el-text-color-regular);
}

.form-dialog-qvil :deep(.el-input__wrapper),
.form-dialog-qvil :deep(.el-textarea__inner) {
  box-shadow: 0 0 0 1px var(--el-border-color) inset;
  border-radius: 6px;
  transition: all 0.2s ease;
}

.form-dialog-qvil :deep(.el-input__wrapper:hover),
.form-dialog-qvil :deep(.el-textarea__inner:hover) {
  box-shadow: 0 0 0 1px var(--el-border-color-hover) inset;
}

.form-dialog-qvil :deep(.el-input__wrapper.is-focus),
.form-dialog-qvil :deep(.el-textarea__inner:focus) {
  box-shadow: 0 0 0 1px var(--el-color-primary) inset;
}

/* Select组件样式优化 */
.form-dialog-qvil :deep(.el-select) {
  width: 100%;
}

.form-dialog-qvil :deep(.el-select__tags) {
  padding-right: 30px;
  flex-wrap: wrap;
  align-items: center;
  min-height: 32px;
  height: auto !important;
  max-width: 100%;
}

.form-dialog-qvil :deep(.el-input__wrapper) {
  height: auto;
  padding-top: 3px;
  padding-bottom: 3px;
}

.form-dialog-qvil :deep(.el-select__tags-text) {
  display: inline-block;
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.form-dialog-qvil :deep(.el-tag) {
  margin: 2px 4px 2px 0;
}

.form-dialog-qvil :deep(.el-tag--info) {
  background-color: var(--el-fill-color-light);
  border-color: var(--el-border-color-lighter);
  color: var(--el-text-color-regular);
}

.form-dialog-qvil :deep(.el-select .el-select__tags .el-tag .el-tag__close) {
  right: -4px;
}

.form-dialog-qvil :deep(.el-form-item.is-error .el-input__wrapper) {
  box-shadow: 0 0 0 1px var(--el-color-danger) inset !important;
}

.dialog-footer {
  display: flex;
  justify-content: flex-end;
  gap: 12px;
}

.form-dialog-qvil :deep(.el-form-item) {
  margin-bottom: 20px;
}
</style>
